package com.jmye.coding.juc.future;

import org.junit.Test;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * @description:
 * @author: jmye
 * @date: 2025/7/3 20:24
 **/

public class CompletableFutureTest {

    @Test
    public void testComplete() throws ExecutionException, InterruptedException {
        CompletableFuture<String> future = new CompletableFuture<>();

        new Thread(() -> {
            try {
                Thread.sleep(2000);
                future.complete("hello world");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        System.out.println("获取线程结果 ==>");
        String result = future.get();
        System.out.println("result = " + result);

    }

    @Test
    public void testRunAsync() throws ExecutionException, InterruptedException {
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(2000);
                System.out.println("runAsync ==> " + Thread.currentThread().getName());
                System.out.println("runAsync ==> 任务执行完成");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        voidCompletableFuture.get();
        System.out.println("main ==> " + Thread.currentThread().getName());
        System.out.println("main ==> 程序执行结束");
    }

    @Test
    public void testSupplyAsync() throws ExecutionException, InterruptedException {
        CompletableFuture<String> stringCompletableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(2000);
                System.out.println("supplyAsync ==> " + Thread.currentThread().getName());
                System.out.println("supplyAsync ==> 获取结果");
                return "hello world";
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "error";
        });

        String result = stringCompletableFuture.get();
        System.out.println("result = " + result);
        System.out.println("main ==> " + Thread.currentThread().getName());
    }

    @Test
    public void testThenRun() throws ExecutionException, InterruptedException {
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(2000);
                System.out.println("supplyAsync ==> " + Thread.currentThread().getName());
                System.out.println("supplyAsync ==> 获取结果");
                return "hello world";
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "error";
        }).thenRun(() -> {
            System.out.println("supplyAsync 执行结束后执行");
        });

        voidCompletableFuture.get();
        System.out.println("main ==> " + Thread.currentThread().getName());
        System.out.println("main ==> " + "程序执行结束");
    }

    @Test
    public void testThenAccept() throws ExecutionException, InterruptedException {
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(2000);
                System.out.println("supplyAsync ==> " + Thread.currentThread().getName());
                System.out.println("supplyAsync ==> 获取结果");
                return "supplyAsync 的返回值";
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "error";
        }).thenAccept(result -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("result = " + result);
        });

        voidCompletableFuture.get();
        System.out.println("main ==> " + Thread.currentThread().getName());
        System.out.println("main ==> " + "程序执行结束");
    }

    @Test
    public void testThenApply() throws ExecutionException, InterruptedException {
        CompletableFuture<String> stringCompletableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(2000);
                System.out.println("supplyAsync ==> " + Thread.currentThread().getName());
                System.out.println("supplyAsync ==> 获取结果");
                return "supplyAsync 的返回值";
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "error";
        }).thenApply(result -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("result = " + result);
            return "thenApply 的返回值";
        });

        String result = stringCompletableFuture.get();
        System.out.println("result = " + result);
        System.out.println("main ==> " + Thread.currentThread().getName());
        System.out.println("main ==> " + "程序执行结束");
    }

    @Test
    public void testThenComposeGettingStarted() throws ExecutionException, InterruptedException {
        CompletableFuture<CompletableFuture<Integer>> completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(2000);
                System.out.println("supplyAsync ==> " + Thread.currentThread().getName());
                System.out.println("supplyAsync ==> 获取结果");
                return "supplyAsync 的返回值";
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "error";
        }).thenApply(new Function<String, CompletableFuture<Integer>>() {
            @Override
            public CompletableFuture<Integer> apply(String s) {
                return CompletableFuture.supplyAsync(new Supplier<Integer>() {
                    @Override
                    public Integer get() {
                        return s.length();
                    }
                });
            }
        });

        Integer result = completableFuture.get().get();
        System.out.println("result = " + result);
    }


    @Test
    public void testThenCompose() throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(2000);
                System.out.println("supplyAsync ==> " + Thread.currentThread().getName());
                System.out.println("supplyAsync ==> 获取结果");
                return "supplyAsync 的返回值";
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "error";
        }).thenCompose(new Function<String, CompletableFuture<Integer>>() {
            @Override
            public CompletableFuture<Integer> apply(String s) {
                return CompletableFuture.supplyAsync(new Supplier<Integer>() {
                    @Override
                    public Integer get() {
                        return s.length();
                    }
                });
            }
        });

        Integer result = integerCompletableFuture.get();
        System.out.println("result = " + result);
    }

    @Test
    public void testThenCombine() throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(2000);
                System.out.println("supplyAsync ==> " + Thread.currentThread().getName());
                System.out.println("supplyAsync ==> 获取结果");
                return "supplyAsync 的返回值";
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "error";
        }).thenCombine(CompletableFuture.supplyAsync(new Supplier<String>() {
            @Override
            public String get() {
                return "future";
            }
        }), new BiFunction<String, String, Integer>() {

            @Override
            public Integer apply(String s, String s2) {
                return s.length() + s2.length();
            }
        });

        Integer result = completableFuture.get();
        System.out.println("result = " + result);
    }

}
